import { _decorator, Component, Node } from 'cc'
const { ccclass, property } = _decorator
import { TileMapMgr } from '../tile/TileMapMgr'
import { createUiNode } from '../utils'
import levels, { ILevel } from '../levels'
import DataMgr from '../runtime/DataMgr'
import { TILE_CONFIGS } from '../utils/constants'
import EventMgr from '../runtime/EventMgr'
import { DIRECTION_ENUM, ENTITY_STATE_ENUM, ENTITY_TYPE_ENUM, EVENT_NAME_ENUM } from '../enums'
import { PlayerMgr } from '../player/PlayerMgr'
import { WoodenSkeletonMgr } from '../woodenSkeleton/WoodenSkeletonMgr'
import { DoorMgr } from '../door/DoorMgr'
import { IronSkeletonMgr } from '../ironSkeleton/IronSkeletonMgr'
import { BurstMgr } from '../burst/BurstMgr'
import { SpikesMgr } from '../spikes/SpikesMgr'
import { SmokeMgr } from '../smoke/SmokeMgr'
import FaderManager from '../runtime/FaderMgr'
import { ShakeMgr } from '../ui/ShakeMgr'
/** 主场景逻辑
 * 舞台节点中放置地图和人物节点
 */
@ccclass('BattleSceneMgr')
export class BattleSceneMgr extends Component {
  level: ILevel
  stage: Node
  private smokeLayer: Node

  onLoad(): void {
    DataMgr.Instance.level = 1 // 初始化设置关卡数
    // 监听下一关事件
    EventMgr.Instance.on(EVENT_NAME_ENUM.PLAYER_MOVE_END, this.checkGotoNextLevel, this)
    // 监听烟雾事件
    EventMgr.Instance.on(EVENT_NAME_ENUM.SHOW_SMOKE, this.generateSmoke, this)
  }

  // 是否跳转下一关
  checkGotoNextLevel() {
    const { x: playerX, y: playerY } = DataMgr.Instance.player
    const { x: doorX, y: doorY, state: doorState } = DataMgr.Instance.door
    if (playerX === doorX && playerY === doorY && doorState === ENTITY_STATE_ENUM.DEATH) {
      this.nextLevel()
    }
  }

  // 下一关卡
  nextLevel() {
    DataMgr.Instance.level++
    this.initLevel()
  }

  start() {
    this.generateStage()
    this.initLevel()
  }

  // 初始化关卡数据
  async initLevel() {
    const level = levels[`level${DataMgr.Instance.level}`]
    if (level) {
      await FaderManager.Instance.fadeIn()
      this.clearStage()
      this.level = level
      // 存储地图信息到单例中，其他类也会用到对应的地图信息
      DataMgr.Instance.mapInfo = this.level.mapInfo // 瓦片数据
      DataMgr.Instance.mapColumnCount = this.level.mapInfo[0].length || 0 // 列数
      DataMgr.Instance.mapRowCount = this.level.mapInfo.length || 0 // 行数

      await Promise.all([
        this.generateTileMap(),
        this.generateBursts(), // 陷阱
        // this.generateSpikes(), // 地刺
        this.generateDoor(),
        this.generateEnemy(),
        this.preInitSmokeLayer(), // 预先生成一个空的烟雾层，这样人物就会盖住烟雾
        this.generatePlayer(),
      ])

      await FaderManager.Instance.fadeOut()
    }
  }

  // 创建舞台节点
  generateStage() {
    this.stage = createUiNode()
    this.stage.setParent(this.node)
    this.stage.addComponent(ShakeMgr) // 添加震动效果
  }

  // 创建地图节点
  async generateTileMap() {
    const tileMap = createUiNode() // 创建地图
    tileMap.setParent(this.stage) // 添加到舞台中
    const tileMgr = tileMap.addComponent(TileMapMgr) // 添加地图组件
    await tileMgr.init()

    this.setPos()
  }

  // 设置舞台偏移位置到正中间
  setPos() {
    const { mapColumnCount, mapRowCount } = DataMgr.Instance
    // 整个舞台偏移舞台长宽各一半
    const disX = (TILE_CONFIGS.TILE_WIDTH * mapRowCount) / 2
    const disY = (TILE_CONFIGS.TILE_HEIGHT * mapColumnCount) / 2 + 80
    this.stage.setPosition(-disX, disY)

    this.stage.getComponent(ShakeMgr).stop() // 舞台初始化时，不需要震动
  }

  // 切换关卡时重置舞台信息
  clearStage() {
    this.stage.destroyAllChildren()
    DataMgr.Instance.reset()
  }

  // 创建人物节点
  async generatePlayer() {
    const player = createUiNode()
    player.setParent(this.stage) // 添加到舞台中
    const playerMgr = player.addComponent(PlayerMgr)
    await playerMgr.init(this.level.player)
    DataMgr.Instance.player = playerMgr // 保存人物角色数据到数据中心
    EventMgr.Instance.emit(EVENT_NAME_ENUM.PLAYER_BORN) // 触发角色初始化完成事件
  }

  // 创建敌人节点
  async generateEnemy() {
    const promises = []
    // 遍历敌人数组数据
    for (let i = 0; i < this.level.enemies.length; i++) {
      const enemy = this.level.enemies[i] // 获取敌人数据
      const enemyNode = createUiNode() // 创建空节点
      enemyNode.setParent(this.stage) // 添加新建节点的父节点
      const mgrSrcipt = enemy.type === ENTITY_TYPE_ENUM.WOODENSKELETON ? WoodenSkeletonMgr : IronSkeletonMgr
      const enemyMgr = enemyNode.addComponent(mgrSrcipt) // 给新建节点添加脚本
      promises.push(enemyMgr.init(enemy)) // 添加初始化脚本执行逻辑到promise后续通过promise.all执行
      DataMgr.Instance.enemies.push(enemyMgr) // 添加当前敌人的数据到数据中心
    }
    await Promise.all(promises) // 统一执行所有敌人的初始化脚本
    // // 木骷髅
    // const woodenEnemy = createUiNode()
    // woodenEnemy.setParent(this.stage)
    // const woodenSkeletonMgr = woodenEnemy.addComponent(WoodenSkeletonMgr)
    // // 铁骷髅
    // const ironEnemy = createUiNode()
    // ironEnemy.setParent(this.stage)
    // const ironSkeletonMgr = ironEnemy.addComponent(IronSkeletonMgr)

    // await woodenSkeletonMgr.init({
    //   x: 2,
    //   y: -4,
    //   direction: DIRECTION_ENUM.TOP,
    //   state: ENTITY_STATE_ENUM.IDLE,
    //   type: ENTITY_TYPE_ENUM.WOODENSKELETON,
    // })
    // await ironSkeletonMgr.init({
    //   x: 2,
    //   y: -2,
    //   direction: DIRECTION_ENUM.TOP,
    //   state: ENTITY_STATE_ENUM.IDLE,
    //   type: ENTITY_TYPE_ENUM.IRONSKELETON,
    // })
    // DataMgr.Instance.enemies.push(woodenSkeletonMgr) // 保存敌人数据到数据中心
    // DataMgr.Instance.enemies.push(ironSkeletonMgr) // 保存敌人数据到数据中心
  }

  // 创建门节点
  async generateDoor() {
    const door = createUiNode()
    door.setParent(this.stage)
    const doorMgr = door.addComponent(DoorMgr)
    await doorMgr.init(this.level.door)
    DataMgr.Instance.door = doorMgr // 保存人物角色数据到数据中心
  }

  // 创建陷阱节点
  async generateBursts() {
    const promises = []
    for (let i = 0; i < this.level.bursts.length; i++) {
      const burst = this.level.bursts[i]
      const burstNode = createUiNode()
      burstNode.setParent(this.stage)
      const burstMgr = burstNode.addComponent(BurstMgr)
      promises.push(burstMgr.init(burst))
      DataMgr.Instance.bursts.push(burstMgr)
    }
    await Promise.all(promises)
    // const bursts = createUiNode()
    // bursts.setParent(this.stage)
    // const burstMgr = bursts.addComponent(BurstMgr)
    // await burstMgr.init({
    //   x: 2,
    //   y: -6,
    //   direction: DIRECTION_ENUM.TOP,
    //   state: ENTITY_STATE_ENUM.IDLE,
    //   type: ENTITY_TYPE_ENUM.BURST,
    // })
    // DataMgr.Instance.bursts.push(burstMgr) // 保存陷阱数据到数据中心
  }

  // 创建地刺节点
  async generateSpikes() {
    const promises = []
    for (let i = 0; i < this.level.spikes.length; i++) {
      const spike = this.level.spikes[i]
      const spikeNode = createUiNode()
      spikeNode.setParent(this.stage)
      const spikesMgr = spikeNode.addComponent(SpikesMgr)
      promises.push(spikesMgr.init(spike))
      DataMgr.Instance.spikes.push(spikesMgr)
    }
    await Promise.all(promises)
    // const spikes = createUiNode()
    // spikes.setParent(this.stage)
    // const spikesMgr = spikes.addComponent(SpikesMgr)
    // await spikesMgr.init({
    //   x: 3,
    //   y: -2,
    //   type: ENTITY_TYPE_ENUM.SPIKES_ONE,
    //   count: 0,
    // })
    // DataMgr.Instance.spikes.push(spikesMgr) // 保存地刺数据到数据中心
  }

  // 预先生成烟雾层
  async preInitSmokeLayer() {
    this.smokeLayer = createUiNode()
    this.smokeLayer.setParent(this.stage)
  }

  // 创建烟雾
  async generateSmoke(x: number, y: number, direction: DIRECTION_ENUM) {
    const smokeItem = DataMgr.Instance.smokes.find(smoke => smoke.state === ENTITY_STATE_ENUM.DEATH)
    if (smokeItem) {
      console.log('从缓存池中获取烟雾')
      smokeItem.x = x
      smokeItem.y = y
      smokeItem.direction = direction
      smokeItem.state = ENTITY_STATE_ENUM.IDLE
    } else {
      const smoke = createUiNode()
      smoke.setParent(this.smokeLayer)
      const smokeMgr = smoke.addComponent(SmokeMgr)
      await smokeMgr.init({
        x,
        y,
        direction,
        type: ENTITY_TYPE_ENUM.SMOKE,
        state: ENTITY_STATE_ENUM.IDLE,
      })
      DataMgr.Instance.smokes.push(smokeMgr) // 保存烟雾数据到数据中心
    }
  }

  onDestroy(): void {
    EventMgr.Instance.off(EVENT_NAME_ENUM.PLAYER_MOVE_END, this.nextLevel)
  }
}
